package rpc

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/smallnest/rpcx/client"
	"github.com/smallnest/rpcx/protocol"
	"gorm.io/gorm"
	"log"
	"os"
	"path/filepath"
	"pm/config"
	"pm/db"
	"pm/model"
	process2 "pm/process"
	"pm/util"
	"strconv"
	"strings"
	"time"
)

type packageClient struct {

}

func (c *packageClient)CheckPackages(){
	d, _ := client.NewPeer2PeerDiscovery(config.ConfigData.RpcMaster + ":" + strconv.Itoa(Port), "")
	opt := client.DefaultOption
	opt.SerializeType = protocol.JSON
	xclient := client.NewXClient("pmon2", client.Failtry, client.RandomSelect, d, opt)
	var reply DataOutput
	params := map[string]interface{}{
		"page":1,
		"page_size":1000,
		"current":1,
	}
	paramsStr,_ := json.Marshal(params)
	xclient.Call(context.Background(), "package.list", string(paramsStr), &reply)
	if reply.Message != nil{
		log.Println("CheckPackages 查询包错误-"+reply.Message.(string))
	}else {
		var listData PackageListOutput
		if err := json.Unmarshal([]byte(reply.Body.(string)), &listData);err != nil{
			log.Print("CheckPackages 解析包列表数据失败-"+err.Error())
			return
		}
		go func(packageList []model.PackageHistory){
			for _,pack := range packageList {
				for _,item := range config.ConfigData.Packages {
                    if pack.Name == item.Name && pack.Current == 1{
						var currentPack model.PackageCurrent
						err := db.NewDb().Model(&model.PackageCurrent{}).Where("name = ?", item.Name).Take(&currentPack).Error
						if err != nil && err != gorm.ErrRecordNotFound{
							continue
						}
						if err == nil && currentPack.Version == pack.Version{
							continue
						}
						targetPath := item.Path
						if item.Type == 2{ //先存放临时目录
							_, fileName := filepath.Split(item.Path)
							targetPath = os.TempDir() + "/" +fileName
						}
						if item.Type == 1{
							process2.NewProcess2().Stop(item.Name)
						}
						var err1 error
						if config.ConfigData.RpcMaster == config.ConfigData.RpcServer{
							err1 = util.CopyFile(pack.FilePath,targetPath)
						}else{
							_,err1 = util.CopyRemoteFile(pack.FilePath, targetPath, config.ConfigData.RpcMaster, config.ConfigData.Ssh.User, config.ConfigData.Ssh.Pwd)
						}
						if err1 != nil{
							log.Println("PackOnUpdate 获取包失败-"+err1.Error())
							continue
						}
						currentPack.Name = item.Name
						currentPack.Version = pack.Version
						db.NewDb().Model(&model.PackageCurrent{}).Save(&currentPack)
						util.ClearDir(item.Path)

						if item.Type == 2{
							util.CopyFile(targetPath,item.Path)
							util.Unzip(item.Path)
						}else {
							process2.NewProcess2().Start(item.Path, strings.Split(item.Args, " "), "")
						}
					}
				}
			}
		}(listData.Data)
	}

}

func (c *packageClient)DoRegister()error{
	d, _ := client.NewPeer2PeerDiscovery(config.ConfigData.RpcMaster + ":" + strconv.Itoa(Port), "")
	opt := client.DefaultOption
	opt.SerializeType = protocol.JSON
	xclient := client.NewXClient("pmon2", client.Failtry, client.RandomSelect, d, opt)
	var reply DataOutput
	params := map[string]interface{}{
		"host":config.ConfigData.RpcServer,
	}
	paramsStr,_ := json.Marshal(params)
	err := xclient.Call(context.Background(), "client.register", string(paramsStr), &reply)
	if err != nil{
		return err
	}
	if reply.Message != nil{
		return errors.New(reply.Message.(string))
	}
	return nil
}



func NewRpcClient()*packageClient{
	if config.ConfigData.RpcServer == ""{
		return nil
	}
	time.Sleep(1 * time.Second)
	pc := &packageClient{}
	if err:= pc.DoRegister();err == nil{
		fmt.Println("rpc register success")
		pc.CheckPackages()
	}else{
		fmt.Println("rpc register error-" + err.Error())
	}
	return pc
}